#ifndef xpack_lang_cxx_slice
#define xpack_lang_cxx_slice
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::lang_cxx::inc
#include"configure/limit.hpp"
#include"define/base_type.hpp"
#include"lang/cxx.hpp"
#include"macro/xdebug_fail.hpp"
#include"math/minimum.hpp"
#pragma pop_macro("xuser")

namespace mixc::lang_cxx{
    template<class item_t>
    template<inc::can_interval interval_t>
    inline cxx<item_t> cxx<item_t>::slice(interval_t range) const {
        xunlikely(range.normalize(xthe->length) == bstate_t::fail){
            return {};
        }

        auto left           = uxx(range->left);
        auto right          = uxx(range->right);

        xunlikely(left > right){
            xdebug_fail(left > right);
            return {};
        }

        auto back           = xthe.backward(left);
        back->length        = right - left + 1;
        return back;
    }

    template<class item_t>
    template<inc::can_interval interval_t, class xalloc_t, class ret_t, class>
    inline ret_t cxx<item_t>::slice(interval_t range, xalloc_t const & alloc) const {
        item_t buffer[inc::limit::lang_cxx_slice];
        auto result         = the_t{};
        auto allocx         = the_t::helper::stream_helper(alloc, xmodify(result.m_ptr), xmodify(result.m_length));
        #define xgen_return()                           \
            if constexpr(inc::is_same<ret_t, the_t>){   \
                return result;                          \
            }                                           \
            else{                                       \
                return;                                 \
            }

        if (range.normalize(xthe->length) == bstate_t::fail){
            xgen_return();
        }

        auto left           = ixx(range->left);
        auto right          = ixx(range->right);
        auto target_length  = uxx(range->length);
        auto stream         = allocx(target_length);

        xunlikely(stream == nullptr){
            xgen_return();
        }

        if (left <= right) {
            stream.output(m_ptr + left, target_length);
        }
        else for(uxx c = target_length, count, i; c; c -= count){
            for(i = 0, count = inc::minimum<uxx>(c, inc::limit::lang_cxx_slice);
                i < count; i++){
                buffer[i]   = m_ptr[left--];
            }
            
            stream.output(buffer, count);
        }

        xgen_return();

        #undef xgen_return
    }
}

#endif
